﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Styx.WoWInternals.DBC;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals;
using Styx.Common;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx;
using System.Diagnostics;
using System.Threading;
using System.IO;
using Styx.CommonBot;
using System.Windows.Forms;
using Styx.CommonBot.Inventory;

namespace KingWoW
{
    public class HolyPriestCombatClass : KingWoWAbstractBaseClass
    {

        private static string Name = "KingWoW 2 HolyPriest";

        #region CONSTANT AND VARIABLES
        //START OF CONSTANTS AND VARIABLES ==============================
        private static bool IsCRPaused = false;
        private static KingWoWUtility utils = null;
        private Movement movement = null;
        private ExtraUtils extra = null;

        private WoWUnit tank = null;
        private WoWUnit lastTank = null;
        private WoWUnit off_tank = null;
        private WoWUnit lastOffTank = null;
        private bool SoloBotType = false;
        private string BaseBot = "unknown";
        private TalentManager talents = null;

        WoWUnit CurrentHealtarget = null;
        WoWUnit healTarget = null;
        WoWUnit AttackTarget = null;
        private double RangeOfAttack = 30f;
        
        private const string TANK_CHANGE = "TANK CHANGED";
        private const string OFF_TANK_CHANGE = "OFFTANK CHANGED";
        private const string FACING = "FACING";

        //START OF SPELLS AND AURAS ==============================
        private const string GUARDIAN_SPIRIT = "Guardian Spirit";
        //private const string SERENDIPITY = "Serendipity";
        private const int DIVINE_INSIGHT_BUFF = 123267;
        private const int LIGHTWELL = 126135;
        private const string LIGHTSPRING = "Lightspring";
        private const int CIRCLE_OF_HEALING = 34861;
        private const int HOLY_WORD_CHASTISE = 88625;
        private const int HOLY_WORD_SERENITY = 88684;
        private const int HOLY_WORD_SANCTUARY = 88685;
        private const int POWER_WORD_SOLACE = 129250;
        private const int DIVINE_STAR = 110744;
        private const int CHAKRA_CHASTISE = 81209;
        private const int CHAKRA_SANCTUARY = 81206;
        private const int CHAKRA_SERENITY = 81208;
        private const int CLARITY_OF_WILL = 155245;
        private const int SHADOW_WORD_PAIN = 589;
        private const int FEAR_WARD = 6346;
        private const int MASS_DISPEL = 32375;
        private const int PRAYER_OF_HEALING = 596;
        private const int PRAYER_OF_MENDING = 33076;
        private const int PRAYER_OF_MENDING_BUFF = 41635;
        private const int POWER_WORD_SHIELD = 17;
        private const int POWER_WORD_FORTITUDE = 21562;
        private const int POWER_INFUSION = 10060;
        private const int PURIFY = 527;
        private const int FLASH_HEAL = 2061;
        private const int HEAL = 2060;
        private const int RENEW = 139;
        private const int SURGE_OF_LIGHT = 114255; // 1 stack --> 128654   talent spell 109186
        private const int HOLY_FIRE = 14914;
        private const int DESPERATE_PRAYER = 19236;
        private const int RESURRECTION = 2006;
        private const int SMITE = 585;
        private const int FADE = 586;
        private const int SHADOWFIEND = 34433;
        private const int MINDBENDER = 123040;
        private const int WEAKENED_SOUL = 6788;
        private const int LEVITATE = 1706;
        private const int CASCADE = 121135;
        private const int HALO = 120517;
        private const int SERENDIPITY_BUFF = 63735;


        private const int DIVINE_HYMN = 64843;

        
        
        private const string SPIRIT_OF_REDEMPTION = "Spirit of Redemption";
        private const int ANGELIC_FEATHER = 121536;
        private const int ANGELIC_FEATHER_AURA = 121557;
        private const int BINDING_HEAL = 32546;

        //private const string DRINK = "Drink";
        //private const string FOOD = "Food";

        //END OF SPELLS AND AURAS ==============================

        private static bool NeedPrecombat = false;
        private static System.Timers.Timer PrecombatTimer = new System.Timers.Timer();
        //END OF CONSTANTS ==============================
        #endregion

        private bool Precombat()
        {
            if (NeedPrecombat && !Me.Combat)
            {
                if (!Me.IsCasting && /*!utils.IsGlobalCooldown() &&*/ !Me.IsMoving && tank != null && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40f && utils.IsHealableByMe(tank) && tank.InLineOfSpellSight
                    && !utils.isAuraActive(PRAYER_OF_MENDING_BUFF, tank) && utils.AOEHealCount(tank, 100, 20f, HolyPriestSettings.Instance.HealNPC) >= 2)
                {
                    if (HolyPriestSettings.Instance.Use_PoM && utils.CanCast(PRAYER_OF_MENDING)
                        && ((tank.Guid != Me.Guid && HolyPriestSettings.Instance.RotationType != HolyPriestSettings.Rotation.PVP) || HolyPriestSettings.Instance.RotationType == HolyPriestSettings.Rotation.PVP))
                    {
                        utils.LogHealActivity(tank, " PRAYER_OF_MENDING", tank.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, tank);
                    }
                }
                if (!Me.IsCasting && /*!utils.IsGlobalCooldown() &&*/ !Me.IsMoving && off_tank != null && off_tank.IsAlive && off_tank.Distance - off_tank.CombatReach - 1 <= 40f && utils.IsHealableByMe(off_tank) && off_tank.InLineOfSpellSight
                    && !utils.isAuraActive(PRAYER_OF_MENDING_BUFF, off_tank) && utils.AOEHealCount(off_tank, 100, 20f, HolyPriestSettings.Instance.HealNPC) >= 2)
                {
                    if (HolyPriestSettings.Instance.Use_PoM && utils.CanCast(PRAYER_OF_MENDING)
                        && ((off_tank.Guid != Me.Guid && HolyPriestSettings.Instance.RotationType != HolyPriestSettings.Rotation.PVP) || HolyPriestSettings.Instance.RotationType == HolyPriestSettings.Rotation.PVP))
                    {
                        utils.LogHealActivity(off_tank, " PRAYER_OF_MENDING", off_tank.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, off_tank);
                    }
                }
                //Prayer of mending
                if (!Me.IsCasting && /*!utils.IsGlobalCooldown() &&*/ !Me.IsMoving && HolyPriestSettings.Instance.Use_PoM && utils.CanCast(PRAYER_OF_MENDING))
                {
                    WoWUnit candidatePoM = utils.GetNeedMyAuraTarget("Prayer of Mending", 40f, HolyPriestSettings.Instance.HealNPC);
                    if (candidatePoM != null)
                    {
                        utils.LogActivity("Precombat PoM: " + candidatePoM.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, candidatePoM);
                    }
                }
                if (tank != null && tank.IsAlive && tank.Distance < 40 && tank.InLineOfSpellSight)
                {
                    if (utils.MyAuraTimeLeft(RENEW, tank) <= 2000 && utils.CanCast(RENEW))
                    {
                        utils.LogHealActivity(tank, "Precombat MAIN TANK: RENEW", tank.SafeName);
                        return utils.Cast(RENEW, tank);
                    }
                }
                if (off_tank != null && off_tank.IsAlive && off_tank.Distance < 40 && off_tank.InLineOfSpellSight)
                {
                    if (utils.MyAuraTimeLeft(RENEW, off_tank) <= 2000 && utils.CanCast(RENEW))
                    {
                        utils.LogHealActivity(off_tank, "Precombat OFF TANK: RENEW", off_tank.SafeName);
                        return utils.Cast(RENEW, off_tank);
                    }
                }
                
            }
            return false;
        }

        #region Hotkeys
        private static Hotkey pauseHotkey, sanctuaryHotkey, renewHotkey, chakaHotkey, massDispelHotkey, npcHealHotkey, divineHymnHotkey, precombatHotkey;
        private static bool Blanket_RENEW = false;

        private static void InitializeHotkey()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestHoly)
            {
                HotkeysManager.Initialize(StyxWoW.Memory.Process.MainWindowHandle);
            }
        }

        private static Hotkey RegisterHotkeyAssignment(string name, Keys key, Action<Hotkey> callback)
        {
            Keys keyCode = key & Keys.KeyCode;
            ModifierKeys mods = ModifierKeys.NoRepeat;

            if ((key & Keys.Shift) != 0)
                mods |= ModifierKeys.Shift;
            if ((key & Keys.Alt) != 0)
                mods |= ModifierKeys.Alt;
            if ((key & Keys.Control) != 0)
                mods |= ModifierKeys.Control;

            return HotkeysManager.Register(name, keyCode, mods, callback);
        }

        private static void RegisterHotkeys()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestHoly)
            {
                precombatHotkey = RegisterHotkeyAssignment("HOLY PrecombatHotkey", (Keys)HolyPriestSettings.Instance.PrecombatHotkey, hk =>
                {
                    try
                    {
                        Logging.Write("Precombat HOTKEY PRESSED! I will buff/shield for 60 sec or until inComabt");
                        NeedPrecombat = true;
                        PrecombatTimer.AutoReset = false;
                        PrecombatTimer.Interval = 60000;
                        PrecombatTimer.Start();
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });

                pauseHotkey = RegisterHotkeyAssignment("HOLY Routine Pause", (Keys)HolyPriestSettings.Instance.PauseKey, hk =>
                {
                    try
                    {
                        if (!IsCRPaused)
                        {
                            IsCRPaused = true;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 Paused!')");
                            Logging.Write("KingWoW Routine Paused!");
                        }
                        else
                        {
                            IsCRPaused = false;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFF15E61C Resumed!')");
                            Logging.Write("KingWoW Routine Resumed!");
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                sanctuaryHotkey = RegisterHotkeyAssignment("HOLY HWSanctuaryOnHotkey", (Keys)HolyPriestSettings.Instance.HWSanctuaryOnHotkey, hk =>
                {
                    try
                    {
                        Logging.Write("HW: Sanctuary HOTKEY PRESSED!");
                        TryPutSanctuary = true;
                        HotkeyTimer.AutoReset = false;
                        HotkeyTimer.Interval = 2000;
                        HotkeyTimer.Start();
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                renewHotkey = RegisterHotkeyAssignment("HOLY Blanket_RENEW_Hotkey", (Keys)HolyPriestSettings.Instance.Blanket_RENEW_Hotkey, hk =>
                {
                    try
                    {
                        if (Blanket_RENEW)
                        {
                            Blanket_RENEW = false;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 Spam RENEW STOP!')");
                            Logging.Write("Spam RENEW STOP!");
                        }
                        else
                        {
                            Blanket_RENEW = true;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFF15E61C Spam RENEW START!')");
                            Logging.Write("Spam RENEW START!");
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                chakaHotkey = RegisterHotkeyAssignment("HOLY Change_CHAKRA_Hotkey", (Keys)HolyPriestSettings.Instance.Chance_CHAKRA_Hotkey, hk =>
                {
                    try
                    {
                        if (utils.isAuraActive(CHAKRA_SERENITY) && utils.CanCast(CHAKRA_SANCTUARY))
                        {
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 Changing CHAKRA_SANCTUARY')");
                            Logging.Write("Changing Chakra to Sanctuary!");
                            HolyPriestSettings.Instance.ChakraToUse = HolyPriestSettings.ChakraType.SANCTUARY;
                        }
                        else if (utils.isAuraActive(CHAKRA_SANCTUARY) && utils.CanCast(CHAKRA_SERENITY))
                        {
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 Changing CHAKRA_SERENITY')");
                            Logging.Write("Changing Chakra to Serenity!");
                            HolyPriestSettings.Instance.ChakraToUse = HolyPriestSettings.ChakraType.SERENITY;
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                massDispelHotkey = RegisterHotkeyAssignment("HOLY MassDispellOnHotkey", (Keys)HolyPriestSettings.Instance.MassDispellOnHotkey, hk =>
                {
                    try
                    {
                        Logging.Write("MassDispell HOTKEY PRESSED!");
                        TryPutMassDispell = true;
                        HotkeyTimer.AutoReset = false;
                        HotkeyTimer.Interval = 2000;
                        HotkeyTimer.Start();
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                divineHymnHotkey = RegisterHotkeyAssignment("HOLY DivineHymnOnHotkey", (Keys)HolyPriestSettings.Instance.DivineHymnOnHotkey, hk =>
                {
                    try
                    {
                        Logging.Write("Divine Hymn HOTKEY PRESSED!");
                        TryCastDivineHymn = true;
                        HotkeyTimer.AutoReset = false;
                        HotkeyTimer.Interval = 2000;
                        HotkeyTimer.Start();
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                npcHealHotkey = RegisterHotkeyAssignment("HOLY Change_NPC_Healing_Hotkey", (Keys)HolyPriestSettings.Instance.Change_NPC_Healing_Hotkey, hk =>
                {
                    try
                    {
                        if (HolyPriestSettings.Instance.HealNPC)
                        {
                            HolyPriestSettings.Instance.HealNPC = false;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 HealNPC DISABLED!')");
                            Logging.Write("HealNPC DISABLED!");
                        }
                        else
                        {
                            HolyPriestSettings.Instance.HealNPC = true;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFF15E61C HealNPC ENABLED!')");
                            Logging.Write("HealNPC ENABLED!");
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
            }
        }

        private static bool TryPutSanctuary = false;
        private static bool TryPutMassDispell = false;
        private static bool TryCastDivineHymn = false;
        private static System.Timers.Timer HotkeyTimer = new System.Timers.Timer();

        private bool HotkeyHandle()
        {
            if (TryPutSanctuary && !WoWSpell.FromId(HOLY_WORD_SANCTUARY).Cooldown)
            {
                if (!utils.isAuraActive(CHAKRA_SANCTUARY) && utils.CanCast(CHAKRA_SANCTUARY))
                {
                    utils.LogActivity("AUTOMATIC SWITCH CHAKRA_SANCTUARY");
                    utils.Cast(CHAKRA_SANCTUARY);
                }
                if (utils.isAuraActive(CHAKRA_SANCTUARY) && !WoWSpell.FromId(HOLY_WORD_SANCTUARY).Cooldown)
                {
                    utils.LogActivity("HW: Sanctuary On Mouse position");
                    utils.Cast(HOLY_WORD_SANCTUARY);
                    utils.PerformSingleLeftMouseClick();
                    return true;
                }
                
            }
            if (TryPutMassDispell && utils.CanCast(MASS_DISPEL))
            {
                utils.LogActivity("MassDispell On Mouse position");
                utils.Cast(MASS_DISPEL);
                utils.PerformSingleLeftMouseClick();
                return true;
            }
            if (TryCastDivineHymn && utils.CanCast(DIVINE_HYMN))
            {
                utils.LogActivity("DIVINE HYMN");
                return utils.Cast(DIVINE_HYMN);
            }
            return false;
        }

        void HotkeyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            TryPutSanctuary = false;
            TryPutMassDispell = false;
            TryCastDivineHymn = false;
        }

        private static void RemoveHotkeys()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestHoly)
            {
                //Holy HOTKEY
                HotkeysManager.Unregister("HOLY Routine Pause");
                HotkeysManager.Unregister("HOLY HWSanctuaryOnHotkey");
                HotkeysManager.Unregister("HOLY Blanket_RENEW_Hotkey");
                HotkeysManager.Unregister("HOLY Change_CHAKRA_Hotkey");
                HotkeysManager.Unregister("HOLY MassDispellOnHotkey");
                HotkeysManager.Unregister("HOLY Change_NPC_Healing_Hotkey");
                HotkeysManager.Unregister("HOLY DivineHymnOnHotkey");
                HotkeysManager.Unregister("HOLY PrecombatHotkey");
                
                //Disci HOTKEY
                HotkeysManager.Unregister("DISCI Routine Pause");
                HotkeysManager.Unregister("DISCI UseDisciplineAtonementHealingRotation");
                HotkeysManager.Unregister("DISCI BarrierOnHotkey");
                HotkeysManager.Unregister("DISCI Blanket_PWS_Hotkey");
                HotkeysManager.Unregister("DISCI MassDispellOnHotkey");
                HotkeysManager.Unregister("DISCI Change_NPC_Healing_Hotkey");
                //shadow HOTKEY
                HotkeysManager.Unregister("SHADOW Routine Pause");
                HotkeysManager.Unregister("SHADOW MassDispellOnHotkey");
            }
        }

        private static void ReRegisterHotkeys()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestHoly)
            {
                Logging.Write("HOLY: ReRegisterHotkeys");
                RemoveHotkeys();
                RegisterHotkeys();
            }
        }
        #endregion

        public HolyPriestCombatClass()
        {
            utils = new KingWoWUtility();
            movement = new Movement();
            extra = new ExtraUtils();
            tank = null;
            lastTank = null;
            off_tank = null;
            lastOffTank = null;
            SoloBotType = false;
            BaseBot = "unknown";
            talents = new TalentManager();
            nextTimeTryReviveAllowed = DateTime.Now;
            HotkeyTimer.Elapsed += HotkeyTimer_Elapsed;
            PrecombatTimer.Elapsed += PrecombatTimer_Elapsed;
        }

        void PrecombatTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Logging.Write("PrecombatBuff Elapsed: press again to restart 60 more sec PoM & renew spam");
            NeedPrecombat = false;
        }

        private DateTime nextTimeTryReviveAllowed;
        
        public void SetNextTimeTryRevive()
        {
            //3 seconds
            nextTimeTryReviveAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 3000);
        }

        private bool MyDeath()
        {
            if (SoloBotType && Me.IsDead && !Me.IsGhost && nextTimeTryReviveAllowed < DateTime.Now)
            {
                Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                SetNextTimeTryRevive();
            }
            return false;
        }

        public override bool Pulse
        {
            get
            {
                if (Me.IsDead) return MyDeath();
                
                if (Me.Combat || (Me.Mounted && !HolyPriestSettings.Instance.AutoDismountOnCombat) || IsCRPaused || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced || utils.IsGlobalCooldown(true) || utils.MeIsChanneling || Me.IsCasting
                || utils.IsEatingOrDrinking())
                    return false;

                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.SafeName);
                }
                off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.SafeName);
                }
                if (HolyPriestSettings.Instance.BurstSpeedMoving && Me.IsMoving && !Me.Mounted && !Me.IsFalling && !Me.IsDead && !Me.IsGhost
                    && Me.MovementInfo.TimeMoved >= HolyPriestSettings.Instance.MoveTimeForSpeedBuff && !IsCRPaused)
                {
                    if (talents.IsSelected(5) && !utils.isAuraActive(ANGELIC_FEATHER_AURA) && utils.CanCast(ANGELIC_FEATHER))
                    {
                        utils.LogActivity("moving....ANGELIC_FEATHER");
                        utils.Buff(ANGELIC_FEATHER);
                        SpellManager.ClickRemoteLocation(Me.Location);
                        Lua.DoString("SpellStopTargeting()");
                        return true;
                    }
                    if (talents.IsSelected(4) && !utils.isAuraActive(WEAKENED_SOUL, Me) && !utils.isAuraActive(POWER_WORD_SHIELD, Me) && utils.CanCast(POWER_WORD_SHIELD))
                    {
                        utils.LogActivity("moving....POWER_WORD_SHIELD");
                        return utils.Cast(POWER_WORD_SHIELD, Me);
                    }

                }
                if (Precombat()) return true;
                if (HotkeyHandle()) return true;
                //full party or me
                if (!Me.Combat && !IsCRPaused && !Me.Mounted && HolyPriestSettings.Instance.OOCHealing && !utils.IsEatingOrDrinking() )
                {
                    healTarget = utils.GetHealTarget(40f, HolyPriestSettings.Instance.HealNPC); 
                    Resurrect();

                    //HW: Sanctuary
                    CastHW_Sanctuary();           
                    
                    //circle of healing
                    if (utils.CanCast(CIRCLE_OF_HEALING))
                    {
                        WoWUnit coh_target = utils.BestCircleOfHealing_Target(HolyPriestSettings.Instance.CircleOfHealingPercent, HolyPriestSettings.Instance.CircleOfHealingNumber, HolyPriestSettings.Instance.HealNPC);
                        if (coh_target != null)
                        {
                            utils.LogHealActivity(coh_target, "OOC: CIRCLE_OF_HEALING", coh_target.SafeName);
                            return utils.Cast(CIRCLE_OF_HEALING, coh_target);
                        }
                    }
                  
                    //divine star
                    if (!Me.IsMoving && utils.CanCast(DIVINE_STAR))
                    {
                        WoWUnit ds_target = utils.BestDSTarget(HolyPriestSettings.Instance.CascadeHaloPercent, HolyPriestSettings.Instance.CascadeHaloNumber, false);
                        if (ds_target != null && utils.CanCast(DIVINE_STAR, ds_target, true))
                        {
                            ds_target.Face();
                            utils.LogActivity("OOC: DIVINE_STAR", ds_target.SafeName);
                            return utils.Cast(DIVINE_STAR, ds_target);
                        }
                    }

                    //Halo/cascade
                    if ((utils.GetMemberCountBelowThreshold(HolyPriestSettings.Instance.CascadeHaloPercent, 40, HolyPriestSettings.Instance.HealNPC) >= HolyPriestSettings.Instance.CascadeHaloNumber))
                    {
                        if (utils.CanCast(HALO))
                        {
                            utils.LogActivity("OOC: HALO");
                            return utils.Cast(HALO);
                        }
                        else if (utils.CanCast(CASCADE))
                        {
                            utils.LogActivity("OOC: CASCADE");
                            return utils.Cast(CASCADE, Me);
                        }
                    }

                    //Clarity
                    if (utils.CanCast(CLARITY_OF_WILL) && !Me.IsMoving)
                    {
                        if (healTarget != null
                            && utils.AOEHealCount(healTarget, HolyPriestSettings.Instance.PrayerOfHealingPercent, 10f, HolyPriestSettings.Instance.HealNPC) >= HolyPriestSettings.Instance.PrayerOfHealingNumber)
                        {
                            utils.LogActivity("CLARITY_OF_WILL", healTarget.SafeName);
                            return utils.Cast(CLARITY_OF_WILL, healTarget);
                        }
                    }

                    //Prayer Of Healing
                    else if (utils.CanCast(PRAYER_OF_HEALING) && !Me.IsMoving)
                    {
                        WoWUnit poh_target = null;
                        poh_target = utils.BestPoHTarget(HolyPriestSettings.Instance.PrayerOfHealingPercent, HolyPriestSettings.Instance.PrayerOfHealingNumber/*, true*/,HolyPriestSettings.Instance.HealNPC);
                        if (poh_target != null)
                        {
                            utils.LogActivity("OOC: PRAYER_OF_HEALING", poh_target.SafeName);
                            return utils.Cast(PRAYER_OF_HEALING, poh_target);
                        }
                    }

                    if (healTarget != null )
                    {
                        double hp = healTarget.HealthPercent;
                        if (utils.isAuraActive(SURGE_OF_LIGHT, Me)
                            && (hp <= HolyPriestSettings.Instance.SoLPercent
                                || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                                || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                        {
                            utils.LogHealActivity(healTarget, "OOC proc SoL: FLASH_HEAL", healTarget.SafeName);
                            return utils.Cast(FLASH_HEAL, healTarget);
                        }
                        if (!utils.isMyAuraActive(RENEW, healTarget) && utils.CanCast(RENEW)
                            && healTarget.HealthPercent <= HolyPriestSettings.Instance.RenewPercent)
                        {
                            utils.LogHealActivity(healTarget, "OOC: RENEW", healTarget.SafeName);
                            return utils.Cast(RENEW, healTarget);
                        }
                        if (utils.CanCast(HOLY_WORD_SERENITY) && utils.isAuraActive(CHAKRA_SERENITY)
                            && hp <= HolyPriestSettings.Instance.HWSerenityPercent)
                        {
                            utils.LogHealActivity(healTarget, "OOC: HOLY_WORD_SERENITY", healTarget.SafeName);
                            return utils.Cast(HOLY_WORD_SERENITY, healTarget);
                        }
                        if (!Me.IsMoving && hp <= HolyPriestSettings.Instance.HealPercent && utils.CanCast(HEAL))
                        {
                            utils.LogHealActivity(healTarget, "OOC: HEAL", healTarget.SafeName);
                            CurrentHealtarget = healTarget;
                            return utils.Cast(HEAL, healTarget);
                        }
                        
                    }
                }

                if (!Me.Combat && !IsCRPaused && ((tank != null && tank.Combat) || (off_tank != null && off_tank.Combat)))
                    return CombatRotation();
                return false;
            }
        }

        private DateTime nextTimeNormalRotationallowed = DateTime.Now;

        public void SetNextTimeNormalRotation(int time)
        {
            nextTimeNormalRotationallowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, time);
        }

        public bool RenewSpam()
        {
            if (Blanket_RENEW && !Me.IsCasting && !utils.IsGlobalCooldown())
            {
                WoWUnit candidateRenew = utils.GetNeedMyAuraTarget("Renew",40f, HolyPriestSettings.Instance.HealNPC);
                if (candidateRenew != null)
                {
                    utils.LogActivity("SPAM  RENEW: " + candidateRenew.SafeName);
                    return utils.Cast(RENEW, candidateRenew);
                }
            }
            return false;
        }

        public bool OnlyInstantSpellRotation()
        {
            while (ProcWork()) return true;
            extra.UseHealPotion_Healthstone();
            while (extra.UseRacials()) return true;
            while (extra.UseTrinket1()) return true;
            while (extra.UseTrinket2()) return true;
            while (extra.UseManaItem()) return true;
            
            while (Self(true)) return true;
            while (ManaRegen(true)) return true;
            while (Cleansing(true)) return true;
            while (HolyPriestSettings.Instance.SoSEnabled && SoS(true)) return true;
            while (TankHealing(true) || OffTankHealing(true)) return true;
            while (AoE(true)) return true;
            //while (RenewSpam()) return true;
            while (Healing(true)) return true;

            return false;
        }

        public override bool Combat
        {
            get
            {
                if (HolyPriestSettings.Instance.TrySaveMana)
                    StopCastingCheck();
                if ((Me.Mounted && !HolyPriestSettings.Instance.AutoDismountOnCombat)
                    || IsCRPaused || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced
                    || (!ExtraUtilsSettings.Instance.FastRotation && (utils.IsGlobalCooldown() || Me.IsCasting)) || utils.MeIsChanneling
                    || utils.IsEatingOrDrinking() )
                    return false;

                //UPDATE TANK
                //tank = utils.GetTank();
                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.SafeName);
                }
                off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.SafeName);
                }

                healTarget = utils.GetHealTarget(40f, HolyPriestSettings.Instance.HealNPC);
                AttackTarget = utils.getTargetToAttack(RangeOfAttack, tank, false, ExtraUtilsSettings.Instance.UseBossLogic);

                if (!IsCRPaused)
                {
                    if (ExtraUtilsSettings.Instance.UseBossLogic)
                    {
                        int time = 0;
                        time = utils.SpecificEncounterNeedStopCast();
                        if (time == 0)
                            time = utils.SpecificEncounterDontCast();
                        if (time > 0)
                        {
                            SpellManager.StopCasting();
                            utils.LogActivity("STOP CASTING/CHANNELING");
                            SetNextTimeNormalRotation(time);
                        }
                        if (nextTimeNormalRotationallowed > DateTime.Now)
                            OnlyInstantSpellRotation();
                    }

                    return CombatRotation();
                }
                return false;


            }
        }

        public override bool Initialize
        {
            get
            {
                Logging.Write("Ciao " + Me.SafeName);
                Logging.Write("Welcome to " + Name + " custom class");
                Logging.Write("Tanks All HonorBuddy Forum developers for code inspiration!");
                Logging.Write("Powered by Attilio76");
                BotEvents.OnBotStartRequested += new BotEvents.OnBotStartStopRequestedDelegate(BotEvents_OnBotStart);
                
                Logging.Write("Initializing Hotkey");
                InitializeHotkey();
                ReRegisterHotkeys();
                Logging.Write("************ XML CONFIGURATION ************");
                Logging.Write(HolyPriestSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("************ EXTRA CONFIGURATION ************");
                Logging.Write(ExtraUtilsSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                return true; ;
            }
        }

        void BotEvents_OnBotStart(EventArgs args)
        {
            talents.Update();
            BotUpdate();
            ReRegisterHotkeys();
        }

        public override bool UpdateTalentAndGlyph
        {
            get
            {               
                talents.Update();
                if (talents.HasGlyph("Holy Fire"))
                {
                    Logging.Write("Glyph of Holy Fire Detected: range of attack spells incremented to 40");
                    RangeOfAttack = 40f;
                }
                BotUpdate();
                ReRegisterHotkeys();
                return true;
            }
        }

        public void StopCastingCheck()
        {
            //Stop Casting Healing Spells
            if (Me.CastingSpell != null &&
                (Me.CurrentCastId == FLASH_HEAL || Me.CurrentCastId == HEAL))
            {
                if (CurrentHealtarget != null && !CurrentHealtarget.IsAlive)
                {
                    CurrentHealtarget = null;
                    SpellManager.StopCasting();
                    Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit is Dead");
                }

                else if (CurrentHealtarget != null && CurrentHealtarget.IsAlive && !CurrentHealtarget.InLineOfSpellSight)
                {
                    CurrentHealtarget = null;
                    SpellManager.StopCasting();
                    Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit not In Line of Spell Sight");
                }

                else if (CurrentHealtarget != null && CurrentHealtarget.IsAlive && CurrentHealtarget.Distance - CurrentHealtarget.CombatReach - 1 > 40f)
                {
                    CurrentHealtarget = null;
                    SpellManager.StopCasting();
                    Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit out of range");
                }

                else if (CurrentHealtarget != null && CurrentHealtarget.IsAlive &&
                        CurrentHealtarget.HealthPercent >= 99)
                {
                    CurrentHealtarget = null;
                    SpellManager.StopCasting();
                    Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit Full HP");
                }
            }
        }

        public bool SoS(bool onlyinstant=false)
        {
            if (healTarget != null && healTarget.HealthPercent <= HolyPriestSettings.Instance.SoSPercent)
            {
                double hp = healTarget.HealthPercent;

                if (HolyPriestSettings.Instance.UseShieldOnSoSPercent && !utils.isAuraActive(POWER_WORD_SHIELD, healTarget)
                    && !utils.isAuraActive(WEAKENED_SOUL, healTarget)
                    && utils.CanCast(POWER_WORD_SHIELD, healTarget)
                    && utils.CanCast(POWER_WORD_SHIELD))
                {
                    utils.LogHealActivity(healTarget, "SoS: POWER_WORD_SHIELD", healTarget.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, healTarget);
                }
                //Surge of Light
                if (utils.isAuraActive(SURGE_OF_LIGHT, Me)
                        && (hp <= HolyPriestSettings.Instance.SoLPercent
                            || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                            || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                {
                    utils.LogHealActivity(healTarget, "SoS: SoL proc-> FLASH_HEAL", healTarget.SafeName);
                    return utils.Cast(FLASH_HEAL, healTarget);
                }

                //binding Heal
                if (!Me.IsMoving && !onlyinstant && healTarget.Guid != Me.Guid && hp <= HolyPriestSettings.Instance.BindingHealPercent && Me.HealthPercent <= HolyPriestSettings.Instance.BindingHealPercent
                    && utils.CanCast(BINDING_HEAL))
                {
                    utils.LogHealActivity(healTarget, "SoS: BINDING_HEAL", healTarget.SafeName);
                    return utils.Cast(BINDING_HEAL, healTarget);
                }

                //HW: Serenity
                if (utils.CanCast(HOLY_WORD_SERENITY) && utils.isAuraActive(CHAKRA_SERENITY) && hp <= HolyPriestSettings.Instance.HWSerenityPercent)
                {
                    utils.LogHealActivity(healTarget, "SoS: HOLY_WORD_SERENITY", healTarget.SafeName);
                    return utils.Cast(HOLY_WORD_SERENITY, healTarget);
                }
                //Flash heal
                if (!Me.IsMoving && !onlyinstant && hp <= HolyPriestSettings.Instance.FlashHealPercent)
                {
                    if (utils.CanCast(HOLY_WORD_SERENITY) && utils.isAuraActive(CHAKRA_SERENITY))
                    {
                        utils.LogHealActivity(healTarget, "SoS: HOLY_WORD_SERENITY", healTarget.SafeName);
                        return utils.Cast(HOLY_WORD_SERENITY, healTarget);
                    }
                    else if (utils.isAuraActive(SERENDIPITY_BUFF) && utils.PlayerCountBuff(SERENDIPITY_BUFF) == 2 && utils.CanCast(HEAL))
                    {
                        utils.LogHealActivity(healTarget, "SoS: SERENDIPITY_BUFF=2 HEAL", healTarget.SafeName);
                        CurrentHealtarget = healTarget;
                        return utils.Cast(HEAL, healTarget);
                    }
                    else if (utils.CanCast(FLASH_HEAL))
                    {
                        utils.LogHealActivity(healTarget, "SoS: FLASH_HEAL", healTarget.SafeName);
                        CurrentHealtarget = healTarget;
                        return utils.Cast(FLASH_HEAL, healTarget);
                    }
                }
                
            }
            return false;
        }

        public bool CombatRotation()
        {
            while (ProcWork()) return true;
            extra.UseHealPotion_Healthstone();
            if (HotkeyHandle()) return true;
            while (extra.UseRacials()) return true;
            while (extra.UseTrinket1()) return true;
            while (extra.UseTrinket2()) return true;
            while (extra.UseManaItem()) return true;

            if ((SoloBotType || HolyPriestSettings.Instance.movementEnabled) && Me.CurrentTarget != null && Me.IsMoving && Me.CurrentTarget.InLineOfSpellSight && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= HolyPriestSettings.Instance.PullDistance)
            {
                Navigator.PlayerMover.MoveStop();
            }

            if (HolyPriestSettings.Instance.RotationType == HolyPriestSettings.Rotation.PVE)
            {
                while (Self()) return true;
                while (ManaRegen()) return true;
                while (Cleansing()) return true;
                while (HolyPriestSettings.Instance.SoSEnabled && SoS()) return true;
                if (HolyPriestSettings.Instance.PriorizeTankHealing)
                {
                    while(TankHealing(false)) return true;
                    while (OffTankHealing(false)) return true;
                }
                
                while (AoE()) return true;
                if (!HolyPriestSettings.Instance.PriorizeTankHealing)
                {
                    while (TankHealing(false) || OffTankHealing(false)) return true;
                }
                //while (RenewSpam()) return true;
                while (Healing()) return true;

            }
            else if (HolyPriestSettings.Instance.RotationType == HolyPriestSettings.Rotation.PVP)
            {

                while (Self()) return true;
                while (ManaRegen()) return true;
                while (Cleansing()) return true;
                while (TankHealing()) return true;
                
                while (AoE()) return true;
                //while (RenewSpam()) return true;
                while (Healing()) return true;
                Dps();
                return true;
            }

            else if (HolyPriestSettings.Instance.RotationType == HolyPriestSettings.Rotation.QUESTING)
            {
                while (Self()) return true;
                while (ManaRegen()) return true;
                while (Cleansing()) return true;
                Dps();
                return true;
            }
            else
                utils.LogActivity("NO VALID ROTATION ");
            return false;

        }

        public override bool NeedRest
        {
            get
            {
                if (Me.IsDead || Me.Mounted || Me.InVehicle || (Me.HealthPercent >= 100 && Me.ManaPercent >= 100)) return false;
                if (utils.IsEatingOrDrinking())
                    return true;
                if (Me.ManaPercent <= HolyPriestSettings.Instance.ManaPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem mydrink = Consumable.GetBestDrink(false);
                    if (mydrink != null)
                    {
                        utils.LogActivity("Drinking");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                if (Me.HealthPercent <= HolyPriestSettings.Instance.HealthPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem myfood = Consumable.GetBestFood(false);
                    if (myfood != null)
                    {
                        utils.LogActivity("Eating");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                return false;
            }
        }

        public override bool NeedPullBuffs
        {
            get
            {
                return HolyPullBuff();
            }
        }

        public override bool NeedCombatBuffs { get { return Buff(); } }

        public override bool NeedPreCombatBuffs { get { return Buff(); } }

        public override bool Pull
        {
            get
            {
                WoWUnit target = Me.CurrentTarget;
                if (target != null && /*!target.IsFriendly &&*/ target.Attackable && !target.IsDead && !IsCRPaused)
                {
                    if (!target.InLineOfSpellSight || target.Distance > HolyPriestSettings.Instance.PullDistance)
                    {
                        //Logging.Write("pull: AttackTarget distance=" + AttackTarget.Distance + " moving in range");
                        movement.KingHealMove(target, HolyPriestSettings.Instance.PullDistance);
                    }
                    if (!Me.IsFacing(target) && HolyPriestSettings.Instance.AutofaceTarget && !Me.IsMoving)
                    {
                        utils.LogActivity(FACING, target.SafeName);
                        Me.SetFacing(target);
                    }

                    if (talents.IsSelected(9) && utils.GetSpellCooldown(POWER_WORD_SOLACE).Milliseconds <= 2 * StyxWoW.WoWClient.Latency)
                    {
                        utils.LogActivity("PULL: POWER_WORD_SOLACE", target.SafeName);
                        return utils.Cast(POWER_WORD_SOLACE, target);
                    }

                    if (!talents.IsSelected(9) && utils.CanCast(HOLY_FIRE, target, true) /*&& !Me.IsMoving*/)
                    {
                        utils.LogActivity("PULL: HOLY_FIRE", target.SafeName);
                        return utils.Cast(HOLY_FIRE, target);
                    } 
                    if (utils.CanCast(SMITE) && !Me.IsMoving)
                    {
                        utils.LogActivity("SMITE", target.SafeName);
                        return utils.Cast(SMITE, target);
                    }
                }
                return false;
            }
        }

        private bool HolyPullBuff()
        {
            if (utils.Mounted() || IsCRPaused)
                return false;
            if (!utils.isAuraActive(POWER_WORD_FORTITUDE) && utils.CanCast(POWER_WORD_FORTITUDE))
            {
                utils.LogActivity("POWER_WORD_FORTITUDE");
                utils.Cast(POWER_WORD_FORTITUDE);
            }

            if (!utils.isAuraActive(FEAR_WARD, tank) && utils.CanCast(FEAR_WARD) && HolyPriestSettings.Instance.UseFearWard && tank.InLineOfSpellSight)
            {
                utils.LogActivity("FEAR_WARD", tank.SafeName);
                utils.Cast(FEAR_WARD, tank);
            }
            if (!utils.isAuraActive(POWER_WORD_SHIELD, Me) && !utils.isAuraActive(WEAKENED_SOUL, Me) && utils.CanCast(POWER_WORD_SHIELD))
            {
                utils.LogActivity("POWER_WORD_SHIELD", Me.SafeName);
                utils.Cast(POWER_WORD_SHIELD, Me); //no return see below
            }
            return false; //return false or loop trying cast PULLBUFF (not implemented)
        }

        private bool BotUpdate()
        {
            if (BaseBot.Equals(BotManager.Current.Name))
                return false;
            if (utils.IsBotBaseInUse("LazyRaider") || utils.IsBotBaseInUse("Tyrael")
                || utils.IsBotBaseInUse("Raid Bot") || utils.IsBotBaseInUse("Enyo"))
            {
                SoloBotType = false;
                BaseBot = BotManager.Current.Name;
                Logging.Write("Base bot detected: " + BotManager.Current.Name);
                return true;
            }

            Logging.Write("Base bot detected: " + BotManager.Current.Name);
            SoloBotType = true;
            BaseBot = BotManager.Current.Name;
            return true;


        }

        private bool ManaRegen( bool onlyinstant=false )
        {
            if (AttackTarget != null && Me.Combat && Me.Combat && !Me.IsChanneling && talents.IsSelected(9) && utils.CanCast(POWER_WORD_SOLACE))
            {
                if (!Me.IsFacing(AttackTarget) && !Me.IsMoving)
                    AttackTarget.Face();
                if (Me.IsFacing(AttackTarget))
                {
                    utils.LogActivity("POWER_WORD_SOLACE", AttackTarget.SafeName);
                    return utils.Cast(POWER_WORD_SOLACE, AttackTarget);
                }
            }
            if (Me.Combat && AttackTarget != null &&
                ((HolyPriestSettings.Instance.CDUsePet == HolyPriestSettings.CDUseType.BOSS && extra.IsTargetBoss())
                    || HolyPriestSettings.Instance.CDUsePet == HolyPriestSettings.CDUseType.COOLDOWN))
            {
                if (Me.ManaPercent <= HolyPriestSettings.Instance.ShadowFiendPercent && utils.CanCast(SHADOWFIEND))
                {
                    utils.LogActivity("SHADOWFIEND", AttackTarget.SafeName);
                    return utils.Cast(SHADOWFIEND, AttackTarget);
                }

                else if (Me.ManaPercent <= HolyPriestSettings.Instance.ShadowFiendPercent && utils.CanCast(MINDBENDER))
                {
                    utils.LogActivity("MINDBENDER", AttackTarget.SafeName);
                    return utils.Cast(MINDBENDER, AttackTarget);
                }
            }

            return false;
        }
        
        private bool Ligthwell()
        {
            if (Me.Combat && (utils.CanCast(LIGHTWELL) || utils.CanCast(LIGHTSPRING))
                && (!HolyPriestSettings.Instance.LightwellOnlyOnBoss || (HolyPriestSettings.Instance.LightwellOnlyOnBoss && Me.CurrentTarget != null && Me.CurrentTarget.IsBoss))
                && HolyPriestSettings.Instance.AutoCastLightwell && utils.GetMemberCountBelowThreshold(50,40f, HolyPriestSettings.Instance.HealNPC) >= 1)
            {
                if(utils.CanCast(LIGHTWELL))
                {
                    utils.LogActivity("LIGHTWELL/LIGHTSPRING");
                    utils.Cast(LIGHTWELL);
                    return SpellManager.ClickRemoteLocation(Me.Location);
                }
                else if (utils.CanCast(LIGHTSPRING))
                {
                    utils.LogActivity(LIGHTSPRING);
                    utils.Cast(LIGHTSPRING);
                    return SpellManager.ClickRemoteLocation(Me.Location);
                }

            }
            return false;
        }

        private bool Self(bool onlyinstant=false)
        {

            if (Me.Combat && Me.HealthPercent <= HolyPriestSettings.Instance.DesperatePrayerPercent && utils.CanCast(DESPERATE_PRAYER))
            {
                utils.LogHealActivity(Me, "DESPERATE_PRAYER");
                return utils.Cast(DESPERATE_PRAYER);
            }

            if (Me.Combat && HolyPriestSettings.Instance.SelfHealingPriorityEnabled && Me.HealthPercent <= HolyPriestSettings.Instance.SelfHealingPriorityHP)
            {
                //guardian Spirit
                if (Me.HealthPercent <= HolyPriestSettings.Instance.GuardianSpiritPercent && utils.CanCast(GUARDIAN_SPIRIT))
                {
                    utils.LogHealActivity(Me, GUARDIAN_SPIRIT, Me.SafeName);
                    return utils.Cast(GUARDIAN_SPIRIT,Me);
                }
                if (utils.CanCast(HOLY_WORD_SERENITY) && utils.isAuraActive(CHAKRA_SERENITY) && Me.HealthPercent <= HolyPriestSettings.Instance.HWSerenityPercent)
                {
                    utils.LogHealActivity(Me, "HOLY_WORD_SERENITY", Me.SafeName);
                    return utils.Cast(HOLY_WORD_SERENITY);
                }
                if (!utils.isAuraActive(POWER_WORD_SHIELD, Me) && !utils.isAuraActive(WEAKENED_SOUL, Me) && utils.CanCast(POWER_WORD_SHIELD))
                {
                    utils.LogHealActivity(Me, "POWER_WORD_SHIELD", Me.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, Me);
                }
                if (!onlyinstant && Me.HealthPercent <= HolyPriestSettings.Instance.FlashHealPercent)
                {
                    if (utils.isAuraActive(SERENDIPITY_BUFF) && utils.PlayerCountBuff(SERENDIPITY_BUFF) == 2 && utils.CanCast(HEAL))
                    {
                        utils.LogHealActivity(Me, "SERENDIPITY_BUFF=2 HEAL", Me.SafeName);
                        CurrentHealtarget = Me;
                        return utils.Cast(HEAL, Me);
                    }
                    else if (utils.CanCast(FLASH_HEAL))
                    {
                        utils.LogHealActivity(Me, "FLASH_HEAL", Me.SafeName);
                        CurrentHealtarget = Me;
                        return utils.Cast(FLASH_HEAL, Me);
                    }
                }               
            }

            //power infusion for heal burst or mana low
            if (Me.Combat && !utils.isAuraActive(POWER_INFUSION) && utils.CanCast(POWER_INFUSION) &&
                ((utils.GetMemberCountBelowThreshold(HolyPriestSettings.Instance.PowerInfusionPercent) >= HolyPriestSettings.Instance.PowerInfusionNumber) ||
                Me.ManaPercent <= HolyPriestSettings.Instance.PowerInfusionManaPercent))
            {
                utils.LogActivity("POWER_INFUSION");
                return utils.Cast(POWER_INFUSION);
            }
            return false;
        }

        private bool AoE(bool onlyinstant=false )
        {
            //if (!HolyPriestSettings.Instance.DisableAOE_HealingRotation)
            //{
                //divine Hymn
                if (!onlyinstant && (utils.GetMemberCountBelowThreshold(HolyPriestSettings.Instance.DHPercent, 40f, HolyPriestSettings.Instance.HealNPC) >= HolyPriestSettings.Instance.DHNumber) && utils.CanCast(DIVINE_HYMN))
                {
                    utils.LogActivity("DIVINE_HYMN");
                    return utils.Cast(DIVINE_HYMN);
                }

                //Lightwell-lightspring
                Ligthwell();

                //circle of healing
                if (utils.CanCast(CIRCLE_OF_HEALING))
                {
                    WoWUnit coh_target = utils.BestCircleOfHealing_Target(HolyPriestSettings.Instance.CircleOfHealingPercent, HolyPriestSettings.Instance.CircleOfHealingNumber, HolyPriestSettings.Instance.HealNPC);
                    if (coh_target != null)
                    {
                        utils.LogHealActivity(coh_target, "CIRCLE_OF_HEALING", coh_target.SafeName);
                        return utils.Cast(CIRCLE_OF_HEALING, coh_target);
                    }
                }

                //divine star
                if (!Me.IsMoving && utils.CanCast(DIVINE_STAR))
                {
                    WoWUnit ds_target = utils.BestDSTarget(HolyPriestSettings.Instance.CascadeHaloPercent, HolyPriestSettings.Instance.CascadeHaloNumber, false);
                    if (ds_target != null && utils.CanCast(DIVINE_STAR, ds_target, true))
                    {
                        ds_target.Face();
                        utils.LogActivity("DIVINE_STAR", ds_target.SafeName);
                        return utils.Cast(DIVINE_STAR, ds_target);
                    }
                }

                //Halo/cascade
                if (!onlyinstant && (utils.GetMemberCountBelowThreshold(HolyPriestSettings.Instance.CascadeHaloPercent, 40, HolyPriestSettings.Instance.HealNPC) >= HolyPriestSettings.Instance.CascadeHaloNumber))
                {
                    if (utils.CanCast(HALO))
                    {
                        utils.LogActivity("HALO");
                        return utils.Cast(HALO);
                    }
                    else if (utils.CanCast(CASCADE))
                    {
                        utils.LogActivity("CASCADE");
                        return utils.Cast(CASCADE, Me);
                    }
                }
                //Clarity
                if (!onlyinstant && utils.CanCast(CLARITY_OF_WILL) && !Me.IsMoving && !Me.IsCasting /*&& !utils.IsGlobalCooldown()*/)
                {
                    if (healTarget != null
                        && utils.AOEHealCount(healTarget, HolyPriestSettings.Instance.PrayerOfHealingPercent, 10f, HolyPriestSettings.Instance.HealNPC) >= HolyPriestSettings.Instance.PrayerOfHealingNumber)
                    {
                        utils.LogActivity("CLARITY_OF_WILL", healTarget.SafeName);
                        return utils.Cast(CLARITY_OF_WILL, healTarget);
                    }
                }

                //Prayer Of Healing
                if (!onlyinstant && utils.CanCast(PRAYER_OF_HEALING) && !Me.IsMoving && !Me.IsCasting /*&& !utils.IsGlobalCooldown()*/)
                {
                    WoWUnit poh_target = null;
                    if(utils.PlayerCountBuff(SERENDIPITY_BUFF) == 2)
                        poh_target = utils.BestPoHTarget(HolyPriestSettings.Instance.TwoSerendipityPrayerOfHealingPercent, HolyPriestSettings.Instance.TwoSerendipityPrayerOfHealingNumber/*, true*/, HolyPriestSettings.Instance.HealNPC);
                    if (poh_target != null)
                    {
                        utils.LogActivity("TWO_SERENDIPITY_BUFF: PRAYER_OF_HEALING", poh_target.SafeName);
                        return utils.Cast(PRAYER_OF_HEALING, poh_target);
                    }
                    if (utils.PlayerCountBuff(SERENDIPITY_BUFF) == 1)
                        poh_target = utils.BestPoHTarget(HolyPriestSettings.Instance.OneSerendipityPrayerOfHealingPercent, HolyPriestSettings.Instance.OneSerendipityPrayerOfHealingNumber/*, true*/, HolyPriestSettings.Instance.HealNPC);
                    if (poh_target != null)
                    {
                        utils.LogActivity("ONE_SERENDIPITY_BUFF: PRAYER_OF_HEALING", poh_target.SafeName);
                        return utils.Cast(PRAYER_OF_HEALING, poh_target);
                    }
                    if(poh_target == null)
                        poh_target = utils.BestPoHTarget(HolyPriestSettings.Instance.PrayerOfHealingPercent, HolyPriestSettings.Instance.PrayerOfHealingNumber/*, true*/, HolyPriestSettings.Instance.HealNPC);
                    if (poh_target != null)
                    {
                        utils.LogActivity("PRAYER_OF_HEALING", poh_target.SafeName);
                        return utils.Cast(PRAYER_OF_HEALING, poh_target);
                    }
                }

                //HW: Sanctuary
                CastHW_Sanctuary();

                //Prayer of mending
                if (!Me.IsCasting && /*!utils.IsGlobalCooldown() &&*/ !Me.IsMoving && !onlyinstant && tank != null && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40f && tank.InLineOfSpellSight
                    && !utils.isAuraActive(PRAYER_OF_MENDING_BUFF, tank) && utils.AOEHealCount(tank, 100, 20f, HolyPriestSettings.Instance.HealNPC) >= 2)
                {
                    if (HolyPriestSettings.Instance.Use_PoM && utils.CanCast(PRAYER_OF_MENDING) 
                        && ((tank.Guid != Me.Guid && HolyPriestSettings.Instance.RotationType != HolyPriestSettings.Rotation.PVP) || HolyPriestSettings.Instance.RotationType == HolyPriestSettings.Rotation.PVP))
                    {
                        utils.LogHealActivity(tank, " PRAYER_OF_MENDING", tank.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, tank);
                    }
                }
                if (!Me.IsCasting && /*!utils.IsGlobalCooldown() &&*/ !Me.IsMoving && !onlyinstant && off_tank != null && off_tank.IsAlive && off_tank.Distance - off_tank.CombatReach - 1 <= 40f && off_tank.InLineOfSpellSight
                    && !utils.isAuraActive(PRAYER_OF_MENDING_BUFF, off_tank) && utils.AOEHealCount(off_tank, 100, 20f, HolyPriestSettings.Instance.HealNPC) >= 2)
                {
                    if (HolyPriestSettings.Instance.Use_PoM && utils.CanCast(PRAYER_OF_MENDING) 
                        && ((off_tank.Guid != Me.Guid && HolyPriestSettings.Instance.RotationType != HolyPriestSettings.Rotation.PVP) || HolyPriestSettings.Instance.RotationType == HolyPriestSettings.Rotation.PVP))
                    {
                        utils.LogHealActivity(off_tank, " PRAYER_OF_MENDING", off_tank.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, off_tank);
                    }
                }
                if (!Me.IsCasting && /*!utils.IsGlobalCooldown() &&*/ !Me.IsMoving && !onlyinstant && HolyPriestSettings.Instance.Use_PoM && utils.CanCast(PRAYER_OF_MENDING) && !HolyPriestSettings.Instance.Use_PoM_Only_On_Tank)
                {
                    WoWUnit candidatePoM = utils.GetNeedMyAuraTarget("Prayer of Mending", 40f, HolyPriestSettings.Instance.HealNPC);
                    if (candidatePoM != null)
                    {
                        utils.LogActivity("Precombat PoM: " + candidatePoM.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, candidatePoM);
                    }
                }
            //}
            return false;
        }

        private bool Healing(bool onlyinstant=false )
        {
            //we are targetting an npc to full: if we are at this point then our healing settings cant full
            //the target so we spam Heal
            if (HolyPriestSettings.Instance.HealNPC && HolyPriestSettings.Instance.FullSelectedNPC
                && !Me.IsCasting && !utils.IsGlobalCooldown()
                && Me.CurrentTarget != null && Me.CurrentTarget.IsFriendly && !Me.CurrentTarget.Attackable && !Me.CurrentTarget.IsPlayer
                && !Me.CurrentTarget.IsDead && Me.CurrentTarget.HealthPercent < 99
                && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= 40f && Me.CurrentTarget.InLineOfSpellSight)
            {
                //renew
                if (!utils.isMyAuraActive(RENEW, Me.CurrentTarget) && utils.CanCast(RENEW))
                {
                    utils.LogHealActivity(Me.CurrentTarget, "FULL NPC CURRENT TARGET:RENEW", Me.CurrentTarget.SafeName);
                    return utils.Cast(RENEW, Me.CurrentTarget);
                }
                //HW: Serenity
                if (utils.CanCast(HOLY_WORD_SERENITY) && utils.isAuraActive(CHAKRA_SERENITY))
                {
                    utils.LogHealActivity(Me.CurrentTarget, "FULL NPC CURRENT TARGET:HOLY_WORD_SERENITY", Me.CurrentTarget.SafeName);
                    return utils.Cast(HOLY_WORD_SERENITY, Me.CurrentTarget);
                }
                //Surge of Light
                if (!onlyinstant && !Me.IsMoving && utils.CanCast(FLASH_HEAL))
                {
                    utils.LogHealActivity(healTarget, "FULL NPC CURRENT TARGET: FLASH_HEAL", Me.CurrentTarget.SafeName);
                    CurrentHealtarget = Me.CurrentTarget;
                    return utils.Cast(FLASH_HEAL, Me.CurrentTarget);
                }

                /*if (!onlyinstant && !Me.IsMoving && utils.CanCast(HEAL))
                {
                    utils.LogHealActivity(Me.CurrentTarget, "FULL NPC CURRENT TARGET:HEAL", Me.CurrentTarget.SafeName);
                    CurrentHealtarget = Me.CurrentTarget;
                    return utils.Cast(HEAL, Me.CurrentTarget);
                }*/
            }

            if (healTarget != null)
            {
                double hp = healTarget.HealthPercent;
                    
                //guardian Spirit
                if (!HolyPriestSettings.Instance.GuardianSpiritOnlyOnTanks && healTarget.IsPlayer && healTarget.Combat && hp <= HolyPriestSettings.Instance.GuardianSpiritPercent && utils.CanCast(GUARDIAN_SPIRIT))
                {
                    utils.LogHealActivity(healTarget, GUARDIAN_SPIRIT, healTarget.SafeName);
                    return utils.Cast(GUARDIAN_SPIRIT, healTarget);
                }
                //Surge of Light
                if (utils.isAuraActive(SURGE_OF_LIGHT, Me)
                        && (hp <= HolyPriestSettings.Instance.SoLPercent
                            || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                            || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                {
                    utils.LogHealActivity(healTarget, "SoL proc: FLASH_HEAL", healTarget.SafeName);
                    return utils.Cast(FLASH_HEAL, healTarget);
                }
                //HW: Serenity
                if (utils.CanCast(HOLY_WORD_SERENITY) && utils.isAuraActive(CHAKRA_SERENITY) && hp <= HolyPriestSettings.Instance.HWSerenityPercent)
                {
                    utils.LogHealActivity(healTarget, "HOLY_WORD_SERENITY", healTarget.SafeName);
                    return utils.Cast(HOLY_WORD_SERENITY, healTarget);
                }
                
                //binding Heal
                if (!Me.IsCasting && !utils.IsGlobalCooldown() && !Me.IsMoving && !onlyinstant && healTarget.Guid != Me.Guid && hp <= HolyPriestSettings.Instance.BindingHealPercent && Me.HealthPercent <= HolyPriestSettings.Instance.BindingHealPercent
                    && utils.CanCast(BINDING_HEAL))
                {
                    utils.LogHealActivity(healTarget, "BINDING_HEAL", healTarget.SafeName);
                    return utils.Cast(BINDING_HEAL, healTarget);
                }
                //Flash heal
                if (!Me.IsCasting && !utils.IsGlobalCooldown() && !Me.IsMoving && !onlyinstant)
                {
                    if (utils.CanCast(HOLY_WORD_SERENITY) && utils.isAuraActive(CHAKRA_SERENITY) && hp <= HolyPriestSettings.Instance.FlashHealPercent)
                    {
                        utils.LogHealActivity(healTarget, "HOLY_WORD_SERENITY", healTarget.SafeName);
                        return utils.Cast(HOLY_WORD_SERENITY, healTarget);
                    }
                    else if (utils.isAuraActive(SERENDIPITY_BUFF) && utils.PlayerCountBuff(SERENDIPITY_BUFF) == 2 && utils.CanCast(HEAL) && hp <= HolyPriestSettings.Instance.FlashHealPercent2Serendipity)
                    {
                        utils.LogHealActivity(healTarget, "SERENDIPITY_BUFF=2 FLASH_HEAL", healTarget.SafeName);
                        CurrentHealtarget = healTarget;
                        return utils.Cast(FLASH_HEAL, healTarget);
                    }
                    else if (utils.isAuraActive(SERENDIPITY_BUFF) && utils.PlayerCountBuff(SERENDIPITY_BUFF) == 1 && utils.CanCast(HEAL) && hp <= HolyPriestSettings.Instance.FlashHealPercent1Serendipity)
                    {
                        utils.LogHealActivity(healTarget, "SERENDIPITY_BUFF=1 FLASH_HEAL", healTarget.SafeName);
                        CurrentHealtarget = healTarget;
                        return utils.Cast(FLASH_HEAL, healTarget);
                    }
                    else if (utils.CanCast(FLASH_HEAL) && hp <= HolyPriestSettings.Instance.FlashHealPercent)
                    {
                        utils.LogHealActivity(healTarget, "SERENDIPITY_BUFF=0 FLASH_HEAL", healTarget.SafeName);
                        CurrentHealtarget = healTarget;
                        return utils.Cast(FLASH_HEAL, healTarget);
                    }
                }

                while (RenewSpam()) return true;

                //renew
                if (!utils.isMyAuraActive(RENEW, healTarget) && hp <= HolyPriestSettings.Instance.RenewPercent && utils.CanCast(RENEW))
                {
                    utils.LogHealActivity(healTarget, "RENEW", healTarget.SafeName);
                    return utils.Cast(RENEW, healTarget);
                }
                //Heal
                if (!Me.IsCasting && !utils.IsGlobalCooldown() && hp <= HolyPriestSettings.Instance.HealPercent2Serendipity && utils.CanCast(HEAL)
                    && utils.isAuraActive(SERENDIPITY_BUFF) && utils.PlayerCountBuff(SERENDIPITY_BUFF) == 2 && !onlyinstant)
                {
                    utils.LogHealActivity(healTarget, "SERENDIPITY_BUFF=2 HEAL", healTarget.SafeName);
                    CurrentHealtarget = healTarget;
                    return utils.Cast(HEAL, healTarget);
                }
                if (!Me.IsCasting && !utils.IsGlobalCooldown() && hp <= HolyPriestSettings.Instance.HealPercent1Serendipity && utils.CanCast(HEAL)
                    && utils.isAuraActive(SERENDIPITY_BUFF) && utils.PlayerCountBuff(SERENDIPITY_BUFF) == 1 && !onlyinstant)
                {
                    utils.LogHealActivity(healTarget, "SERENDIPITY_BUFF=1 HEAL", healTarget.SafeName);
                    CurrentHealtarget = healTarget;
                    return utils.Cast(HEAL, healTarget);
                }
                if (!Me.IsCasting && !utils.IsGlobalCooldown() && hp <= HolyPriestSettings.Instance.HealPercent && utils.CanCast(HEAL))
                {
                    if (!onlyinstant)
                    {
                        utils.LogHealActivity(healTarget, "SERENDIPITY_BUFF=0 HEAL", healTarget.SafeName);
                        CurrentHealtarget = healTarget;
                        return utils.Cast(HEAL, healTarget);
                    }
                }
                
            }
            return false;
        }

        private bool TankHealing(bool onlyinstant=false)
        {
            if (tank != null && tank.IsAlive && tank.Distance < 40 && utils.IsHealableByMe(tank) && tank.InLineOfSpellSight && tank.IsValid && !tank.Possessed && tank.VehicleInfo == null)
            {
                //int num_member_for_FHvsH = utils.GetMemberCountBelowThreshold(HolyPriestSettings.Instance.HealPercent, 40, HolyPriestSettings.Instance.HealNPC);
                //guardian Spirit
                if (tank.Combat && tank.HealthPercent <= HolyPriestSettings.Instance.GuardianSpiritPercent && utils.CanCast(GUARDIAN_SPIRIT))
                {
                    utils.LogHealActivity(tank, "MAIN TANK: "+GUARDIAN_SPIRIT, tank.SafeName);
                    return utils.Cast(GUARDIAN_SPIRIT, tank);
                }

                //renew always active on combat tank?
                if (tank.Combat && HolyPriestSettings.Instance.RenewAlwaysActiveOnTank)
                {
                    if (utils.MyAuraTimeLeft(RENEW, tank) <= 2000 && utils.CanCast(RENEW))
                    {
                        utils.LogHealActivity(tank, "MAIN TANK: RENEW", tank.SafeName);
                        return utils.Cast(RENEW, tank);
                    }
                }
            }
            return false;
        }

        private bool OffTankHealing(bool onlyinstant = false)
        {
            if (off_tank != null && off_tank.IsAlive && off_tank.Distance < 40 && utils.IsHealableByMe(off_tank) && off_tank.InLineOfSpellSight && off_tank.IsValid && !off_tank.Possessed && off_tank.VehicleInfo == null)
            {
                //guardian Spirit
                if (off_tank.Combat && off_tank.HealthPercent <= HolyPriestSettings.Instance.GuardianSpiritPercent && utils.CanCast(GUARDIAN_SPIRIT))
                {
                    utils.LogHealActivity(off_tank, "OFF_TANK:  "+GUARDIAN_SPIRIT, off_tank.SafeName);
                    return utils.Cast(GUARDIAN_SPIRIT, off_tank);
                }

                //renew always active on combat off_tank?
                if (off_tank.Combat && HolyPriestSettings.Instance.RenewAlwaysActiveOnTank)
                {
                    if (utils.MyAuraTimeLeft(RENEW, off_tank) <= 2000 && utils.CanCast(RENEW))
                    {
                        utils.LogHealActivity(off_tank, "OFF_TANK:  RENEW", off_tank.SafeName);
                        return utils.Cast(RENEW, off_tank);
                    }
                }
            }
            return false;
        }

        private bool Cleansing(bool onlyinstant=false )
        {
            if (HolyPriestSettings.Instance.UsePurify || HolyPriestSettings.Instance.UseMassDispell)
            {
                WoWUnit player = null;
                if (utils.NeedsDispelPriest(Me, ExtraUtilsSettings.Instance.UseBossLogic))
                    player = Me;
                else if (tank != null && tank.IsAlive && tank.InLineOfSpellSight && tank.Distance - tank.CombatReach - 1 <= 40f && utils.IsHealableByMe(tank) && utils.NeedsDispelPriest(tank, ExtraUtilsSettings.Instance.UseBossLogic))
                    player = tank;
                else if (off_tank != null && off_tank.IsAlive && off_tank.InLineOfSpellSight && off_tank.Distance - off_tank.CombatReach - 1 <= 40f && utils.IsHealableByMe(off_tank) && utils.NeedsDispelPriest(off_tank, ExtraUtilsSettings.Instance.UseBossLogic))
                    player = off_tank;
                else
                    player = utils.GetDispelTargetPriest(40f, HolyPriestSettings.Instance.HealNPC, ExtraUtilsSettings.Instance.UseBossLogic);

                if (player != null )
                {
                    if (!Me.IsMoving && !onlyinstant && HolyPriestSettings.Instance.UseMassDispell && utils.MassDispelCountForPlayer(player, 15f) >= HolyPriestSettings.Instance.MassDispellCount && utils.CanCast(MASS_DISPEL))
                    {
                        utils.LogActivity("MASS_DISPEL", player.SafeName);
                        utils.Cast(MASS_DISPEL);
                        return SpellManager.ClickRemoteLocation(player.Location);
                    }

                    if (HolyPriestSettings.Instance.UsePurify && utils.CanCast(PURIFY))
                    {
                        utils.LogActivity("PURIFY", player.SafeName);
                        return utils.Cast(PURIFY, player);
                    }
                }
            }
            return false;
        }

        private bool Resurrect()
        {
            foreach (WoWPlayer player in utils.GetResurrectTargets(40f))
            {
                if (Blacklist.Contains(player.Guid, BlacklistFlags.All)) continue;
                else
                {
                    if (player.Distance - player.CombatReach - 1 > 40f || !player.InLineOfSpellSight) return false;
                    else if (utils.CanCast(RESURRECTION, player) && HolyPriestSettings.Instance.UseResurrection && !Me.IsMoving)
                    {
                        utils.LogActivity("RESURRECTION", player.SafeName);
                        Blacklist.Add(player, BlacklistFlags.All, new TimeSpan(0, 0, 60));
                        return utils.Cast(RESURRECTION, player);
                    }

                    return false;
                }
            }

            return false;
        }

        private bool Buff()
        {
            if (utils.Mounted() || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || IsCRPaused
                || utils.IsEatingOrDrinking() )
                return false;
            

            if (HolyPriestSettings.Instance.AutoPWFortitude)
            {
                if (!utils.isAuraActive(POWER_WORD_FORTITUDE) && utils.CanCast(POWER_WORD_FORTITUDE))
                {
                    utils.LogActivity("POWER_WORD_FORTITUDE");
                    return utils.Cast(POWER_WORD_FORTITUDE);
                }

                foreach (WoWPlayer player in Me.PartyMembers)
                {
                    if (player.Distance > 40 || player.IsDead || player.IsGhost || !player.InLineOfSpellSight) continue;
                    else if (!utils.isAuraActive(POWER_WORD_FORTITUDE, player) && utils.CanCast(POWER_WORD_FORTITUDE))
                    {
                        utils.LogActivity("POWER_WORD_FORTITUDE", player.SafeName);
                        return utils.Cast(POWER_WORD_FORTITUDE, player);
                    }
                }
            }

            if (tank != null && tank.Combat && !utils.isAuraActive(FEAR_WARD, tank) && utils.CanCast(FEAR_WARD) && HolyPriestSettings.Instance.UseFearWard && tank.InLineOfSpellSight)
            {
                utils.LogActivity("FEAR_WARD", tank.SafeName);
                return utils.Cast(FEAR_WARD, tank);
            }
            if (Me.Combat && (Me.GroupInfo.IsInParty || Me.GroupInfo.IsInRaid) && Me.CurrentMap.IsInstance && (Targeting.GetAggroOnMeWithin(Me.Location, 30) > 0) && utils.CanCast(FADE))
            {
                utils.LogActivity("FADE");
                return utils.Cast(FADE);
            }


            if (HolyPriestSettings.Instance.BurstSpeedMoving && Me.IsMoving && !Me.IsCasting && !Me.IsChanneling && !Me.Mounted && !Me.IsFalling
                && (Me.Combat || Me.MovementInfo.TimeMoved >= HolyPriestSettings.Instance.MoveTimeForSpeedBuff))
            {
                if (talents.IsSelected(5) && !utils.isAuraActive(ANGELIC_FEATHER_AURA)
                    && utils.GetSpellCooldown(ANGELIC_FEATHER).Milliseconds <= StyxWoW.WoWClient.Latency)
                {
                    utils.LogActivity("moving....ANGELIC_FEATHER");
                    utils.Buff(ANGELIC_FEATHER);
                    SpellManager.ClickRemoteLocation(Me.Location);
                    Lua.DoString("SpellStopTargeting()");
                    return true;
                }
                if (talents.IsSelected(4) && !utils.isAuraActive(WEAKENED_SOUL, Me) && !utils.isAuraActive(POWER_WORD_SHIELD, Me) && utils.CanCast(POWER_WORD_SHIELD))
                {
                    utils.LogActivity("moving....POWER_WORD_SHIELD");
                    return utils.Cast(POWER_WORD_SHIELD, Me);
                }

            }

            switch (HolyPriestSettings.Instance.ChakraToUse)
            {
                case HolyPriestSettings.ChakraType.AUTO:
                    {
                        WoWUnit hws_target = null;
                        if (!HolyPriestSettings.Instance.HWSanctuaryOnlyOnHotkey && !Me.IsMoving && !WoWSpell.FromId(HOLY_WORD_SANCTUARY).Cooldown)
                        {
                            if (HolyPriestSettings.Instance.HWSanctuaryOnTank && tank != null && tank.InLineOfSpellSight && tank.Distance <= 40 &&
                                (utils.AOEHealCount((WoWPlayer)tank, HolyPriestSettings.Instance.HWSanctuaryPercent, utils.PW_SanctuaryRadius()) >= HolyPriestSettings.Instance.HWSanctuaryNumber))
                            {
                                hws_target = (WoWPlayer)tank;
                            }
                            else if (!HolyPriestSettings.Instance.HWSanctuaryOnTank)
                            {
                                hws_target = utils.BestHWSanctuaryTargetLocation(HolyPriestSettings.Instance.HWSanctuaryPercent, HolyPriestSettings.Instance.HWSanctuaryNumber, HolyPriestSettings.Instance.HealNPC);
                            }
                            if (hws_target != null)
                            {
                                if (!utils.isAuraActive(CHAKRA_SANCTUARY) && utils.CanCast(CHAKRA_SANCTUARY))
                                {
                                    utils.LogActivity("AUTOMATIC SWITCH CHAKRA_SANCTUARY");
                                    utils.Cast(CHAKRA_SANCTUARY);
                                }
                                if (utils.isAuraActive(CHAKRA_SANCTUARY))
                                {
                                    utils.LogActivity("HOLY_WORD_SANCTUARY", hws_target.SafeName);
                                    utils.Cast(HOLY_WORD_SANCTUARY);
                                    return SpellManager.ClickRemoteLocation(hws_target.Location);
                                }
                            }
                        }
                        else if (!utils.isAuraActive(CHAKRA_SERENITY) && utils.CanCast(CHAKRA_SERENITY))
                        {
                            utils.LogActivity("AUTOMATIC SWITCH CHAKRA_SERENITY");
                            return utils.Cast(CHAKRA_SERENITY);
                        }
                    }
                    break;
                case HolyPriestSettings.ChakraType.SANCTUARY:
                    {
                        if (!utils.isAuraActive(CHAKRA_SANCTUARY) && utils.CanCast(CHAKRA_SANCTUARY))
                        {
                            utils.LogActivity("CHAKRA_SANCTUARY");
                            return utils.Cast(CHAKRA_SANCTUARY);
                        }
                    }
                    break;
                case HolyPriestSettings.ChakraType.SERENITY:
                    {
                        if (!utils.isAuraActive(CHAKRA_SERENITY) && utils.CanCast(CHAKRA_SERENITY))
                        {
                            utils.LogActivity("CHAKRA_SERENITY");
                            return utils.Cast(CHAKRA_SERENITY);
                        }
                    }
                    break;
                case HolyPriestSettings.ChakraType.CHASTISE:
                    {
                        if (!utils.isAuraActive(CHAKRA_CHASTISE) && utils.CanCast(CHAKRA_CHASTISE))
                        {
                            utils.LogActivity("CHAKRA_CHASTISE");
                            return utils.Cast(CHAKRA_CHASTISE);
                        }
                    }
                    break;
            }
            return false;
        }

        private bool Dps()
        {
            WoWUnit target = utils.getTargetToAttack(40, tank, false, ExtraUtilsSettings.Instance.UseBossLogic);
            if (target != null)
            {
                if (!Me.IsMoving && !Me.IsFacing(target) && HolyPriestSettings.Instance.AutofaceTarget)
                    target.Face();

                if (Me.IsFacing(target) && !Me.IsChanneling && talents.IsSelected(9) && utils.CanCast(POWER_WORD_SOLACE))
                {
                    utils.LogActivity("POWER_WORD_SOLACE", target.SafeName);
                    return utils.Cast(POWER_WORD_SOLACE, target);
                }
                if (Me.IsFacing(target) && !talents.IsSelected(9) && utils.CanCast(HOLY_FIRE, target, true))
                {
                    utils.LogActivity("HOLY_FIRE", target.SafeName);
                    return utils.Cast(HOLY_FIRE, target);
                }
                if (Me.IsFacing(target) && utils.CanCast(HOLY_WORD_CHASTISE))
                {
                    utils.LogActivity("HOLY_WORD_CHASTISE", target.SafeName);
                    return utils.Cast(HOLY_WORD_CHASTISE, target);
                }
                if (!utils.isAuraActive(SHADOW_WORD_PAIN, target) && utils.CanCast(SHADOW_WORD_PAIN))
                {
                    utils.LogActivity("SHADOW_WORD_PAIN", target.SafeName);
                    return utils.Cast(SHADOW_WORD_PAIN, target);
                }
                if (Me.IsFacing(target) && utils.CanCast(SMITE) && !Me.IsMoving)
                {
                    utils.LogActivity("SMITE", target.SafeName);
                    return utils.Cast(SMITE, target);
                }
                if (HolyPriestSettings.Instance.movementEnabled && (!target.InLineOfSpellSight || target.Distance > HolyPriestSettings.Instance.PullDistance))
                {
                    movement.KingHealMove(target, HolyPriestSettings.Instance.PullDistance);
                }
            }
            return false;
        }

        private bool ProcWork()
        {
            //Surge of Light
            if (utils.isAuraActive(SURGE_OF_LIGHT, Me))
            {
                if (healTarget != null)
                {
                    double hp = healTarget.HealthPercent;

                    //Surge of Light
                    if (utils.CanCast(FLASH_HEAL) && (hp <= HolyPriestSettings.Instance.SoLPercent
                                                        || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                                                        || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                    {
                        utils.LogActivity("Surge of light proc FLASH_HEAL", healTarget.SafeName);
                        return utils.Cast(FLASH_HEAL, healTarget);
                    }                   
                }
            }

            //Prayer of mending on Divine Insight proc
            if (utils.isAuraActive(DIVINE_INSIGHT_BUFF) && utils.CanCast(PRAYER_OF_MENDING))
            {
                if (healTarget != null)
                {
                    utils.LogActivity("Divine insight proc ending consume PRAYER_OF_MENDING", healTarget.SafeName);
                    return utils.Cast(PRAYER_OF_MENDING, healTarget);
                }
            }
            return false;
        }

        private bool CastHW_Sanctuary()
        {
            WoWUnit hws_target = null;
            if (!HolyPriestSettings.Instance.HWSanctuaryOnlyOnHotkey && !Me.IsMoving && !WoWSpell.FromId(HOLY_WORD_SANCTUARY).Cooldown && utils.isAuraActive(CHAKRA_SANCTUARY, Me))
            {
                if (HolyPriestSettings.Instance.HWSanctuaryOnTank && tank != null && tank.InLineOfSpellSight && tank.Distance <= 40 &&
                    (utils.AOEHealCount((WoWPlayer)tank, HolyPriestSettings.Instance.HWSanctuaryPercent, utils.PW_SanctuaryRadius()) >= HolyPriestSettings.Instance.HWSanctuaryNumber))
                {
                    hws_target = (WoWPlayer)tank;
                }
                else if (!HolyPriestSettings.Instance.HWSanctuaryOnTank)
                {
                    hws_target = utils.BestHWSanctuaryTargetLocation(HolyPriestSettings.Instance.HWSanctuaryPercent, HolyPriestSettings.Instance.HWSanctuaryNumber, HolyPriestSettings.Instance.HealNPC);
                }
                if (hws_target != null)
                {
                    utils.LogActivity("HOLY_WORD_SANCTUARY", hws_target.SafeName);
                    utils.Cast(HOLY_WORD_SANCTUARY);
                    return SpellManager.ClickRemoteLocation(hws_target.Location);
                }
            }
            return false;
        }
    }
}
